using System;
using System.Collections.Generic;
using NFreeMarker.Ext.Beans;
using NFreeMarker.Template;
using NFreeMarker.Template.Utility;

namespace NFreeMarker.Core
{
    /**
     * A built-in that allows us to instantiate an instance of a java class.
     * Usage is something like:
     * &lt;#assign foobar = "foo.bar.MyClass"?new() /&gt;
     */

    internal class NewBuiltIn : BuiltIn
    {
        static readonly Type TmClass = typeof (TemplateModel);
        static readonly Type BeanModelClass = typeof (BeanModel);
        //static Class JYTHON_MODEL_CLASS;
        //static {
        //    try {
        //        JYTHON_MODEL_CLASS = Class.forName("freemarker.ext.jython.JythonModel");
        //    } catch (Throwable e) {
        //        JYTHON_MODEL_CLASS = null;
        //    }
        //}

        protected override ITemplateModel _getAsTemplateModel(Environment env)
        {
            ITemplateModel tm = Target.GetAsTemplateModel(env);
            string classname = null;
            try
            {
                classname = ((ITemplateScalarModel) tm).GetAsString();
            }
            catch (InvalidCastException)
            {
                InvalidTypeException(tm, Target, env, "string");
            }
            catch (NullReferenceException)
            {
                throw new InvalidReferenceException(
                    GetStartLocation() + "\nCould not resolve expression: " + Target, env);
            }
            return new ConstructorFunction(classname, env);
        }

        private class ConstructorFunction : ITemplateMethodModelEx
        {
            private readonly Type _cl;
            private readonly Environment _env;

            public ConstructorFunction(string classname, Environment env)
            {
                _env = env;
                //try
                //{
                    _cl = ClassUtil.ForName(classname);
                    if (!TmClass.IsAssignableFrom(_cl))
                    {
                        throw new TemplateException("Class " + _cl.FullName + " does not implement freemarker.template.TemplateModel", env);
                    }
                    if (BeanModelClass.IsAssignableFrom(_cl))
                    {
                        throw new TemplateException("Bean Models cannot be instantiated using the ?new built-in", env);
                    }
                //    if (JYTHON_MODEL_CLASS != null && JYTHON_MODEL_CLASS.isAssignableFrom(cl)) {
                //        throw new TemplateException("Jython Models cannot be instantiated using the ?new built-in", env);
                //    }
                //}
                //catch (ClassNotFoundException cnfe)
                //{
                //    throw new TemplateException(cnfe, env);
                //}

                throw new NotImplementedException();
            }

            public object Exec(IList<ITemplateModel> arguments)
            {
                IObjectWrapper ow = _env.GetObjectWrapper();
                BeansWrapper bw = ow is BeansWrapper
                    ? (BeansWrapper) ow
                    : BeansWrapper.GetDefaultInstance();
                return bw.NewInstance(_cl, arguments);
            }

            public object Exec(IList<string> arguments)
            {
                throw new NotSupportedException();
            }
        }
    }
}